package com.quzhi.sys.controller.warehouseController;

import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quzhi.common.Result;
import com.quzhi.common.Utils;
import com.quzhi.common.code.Code;
import com.quzhi.common.code.ExportCode;
import com.quzhi.sys.dto.InventoryDto;
import com.quzhi.sys.dto.OrderDto;
import com.quzhi.sys.dto.ProductDto;
import com.quzhi.sys.entity.*;
import com.quzhi.sys.service.impl.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 前端控制器 库存商品
 * </p>
 *
 * @author Xibing
 * @since 2024-07-23
 */
@Slf4j
@RestController
@RequestMapping("/sys/inventory")
public class InventoryController {
    @Autowired
    private InventoryServiceImpl inventoryService;

    @Autowired
    private WarehouseServiceImpl warehouseService;

    @Autowired
    private ProductServiceImpl productService;

    // 记录表
    @Autowired
    private GoodsRecordServiceImpl goodsRecordService;

    @Autowired
    private AddGoodsServiceImpl addGoodsService;


    @Autowired
    private OrderSerialNumberServiceImpl serialNumberService;

    @Autowired
    private GoodsSerialNumberServiceImpl goodsSerialNumberService;


    @Autowired
    private OrderServiceImpl orderService;

    @Autowired
    private OrderSerialNumberServiceImpl orderSerialNumberService;


    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/list")
    public Result<?> getInventoryList(
            @RequestParam(value = "serialNumber", required = false) String serialNumber,
            @RequestParam(value = "productId", required = false) String productId,
            @RequestParam(value = "warehouseId", required = false) String warehouseId,
            @RequestParam(value = "pageNo") Long pageNo,
            @RequestParam(value = "pageSize") Long pageSize
    ) {


        LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasLength(serialNumber), Inventory::getSerialNumber, serialNumber);
        wrapper.eq(StringUtils.hasLength(productId), Inventory::getProductId, productId);
        wrapper.eq(StringUtils.hasLength(warehouseId), Inventory::getWarehouseId, warehouseId);


        Page<Inventory> infoPage = new Page<>(pageNo, pageSize);

        inventoryService.page(infoPage, wrapper);

        List<Inventory> inventories = infoPage.getRecords();
        List<InventoryDto> InventoryDtoList = new ArrayList<>();

        for (Inventory inventory : inventories) {
            InventoryDto inventoryDto = new InventoryDto();
            BeanUtils.copyProperties(inventory, inventoryDto);

            // 查询名称
            LambdaQueryWrapper<Warehouse> warehouseWrapper = new LambdaQueryWrapper<>();
            warehouseWrapper.eq(Warehouse::getId, inventoryDto.getWarehouseId());

            LambdaQueryWrapper<Product> productWraaper = new LambdaQueryWrapper<>();
            productWraaper.eq(Product::getId, inventoryDto.getProductId());

            Warehouse warehouse = warehouseService.getOne(warehouseWrapper);
            Product product = productService.getOne(productWraaper);

            inventoryDto.setWarehouseName(warehouse.getWarehouseName());
            inventoryDto.setGoodsName(product.getGoodsName());

            InventoryDtoList.add(inventoryDto);
        }


        Map<String, Object> data = new HashMap<>();
        data.put("rows", InventoryDtoList);
        data.put("total", infoPage.getTotal());

        return Result.success(data);
    }


    @GetMapping("/{id}")
    public Result<?> getInventoryById(@PathVariable("id") String id) {
        Inventory inventory = inventoryService.getById(id);

        InventoryDto inventoryDto = new InventoryDto();
        BeanUtils.copyProperties(inventory, inventoryDto);


        return Result.success(inventory);
    }

    // 获取对应仓库的商品
    @GetMapping("/getWarehouseInventory")
    public Result<?> getWarehouseInventory(
            @RequestParam(value = "productId", required = false) String productId,
            @RequestParam(value = "warehouseId") String warehouseId) {

        LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Inventory::getWarehouseId, warehouseId);
        wrapper.eq(StringUtils.hasLength(productId), Inventory::getProductId, productId);

        List<Inventory> list = inventoryService.list(wrapper);

        List<InventoryDto> inventoryDtos = new ArrayList<>();

        // 获取所有商品名称和仓库名称
        List<Warehouse> warehouseList = warehouseService.list();
        List<Product> Productlist = productService.list();
        for (Inventory inventory : list) {
            InventoryDto inventoryDto = new InventoryDto();
            BeanUtils.copyProperties(inventory, inventoryDto);
            // 查询名称
            for (Warehouse warehouse : warehouseList) {
                if (warehouse.getId().equals(inventoryDto.getWarehouseId())) {
                    inventoryDto.setWarehouseName(warehouse.getWarehouseName());
                    break;
                }
            }

            for (Product product : Productlist) {
                if (product.getId().equals(inventoryDto.getProductId())) {
                    inventoryDto.setGoodsName(product.getGoodsName());
                    break;
                }
            }

            inventoryDtos.add(inventoryDto);
        }
        return Result.success(inventoryDtos);
    }

    @PostMapping
    public Result<?> addInventory(@RequestBody Inventory inventory) {

        LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Inventory::getSerialNumber, inventory.getSerialNumber());

        Inventory one = inventoryService.getOne(wrapper);

        // 如果仓库存在则不允许添加
        if (one != null) return Result.fail(20002, "该序列号已存在");

        // 添加仓库
        inventory.setId(UUID.randomUUID().toString());
        inventory.setCreateTime(LocalDateTime.now());
        inventory.setUpdateTime(LocalDateTime.now());
        inventoryService.save(inventory);

        return Result.success("添加成功");
    }

    /**
     * 批量添加序列号商品
     *
     * @param
     * @return
     */
    @PostMapping("/addInventoryList")
    public Result<?> addInventoryList(@RequestBody List<Inventory> inventoryList,
                                      @RequestParam(value = "remark", required = false) String remark) {

        // 已存在的序列号
        List<String> isSaveInventory = new ArrayList<>();


        // 保存记录单
        GoodsRecord goodsRecord = new GoodsRecord();

        // 随机生成单号
        List<GoodsRecord> list = goodsRecordService.list();
        boolean flag = true;
        String tj = "";
        do {
            tj = Utils.generateRandomNumberString("TJ");
            for (GoodsRecord record : list) {
                flag = !record.getTableNumber().equals(tj);
            }
        } while (!flag);

        goodsRecord.setId(UUID.randomUUID().toString());
        goodsRecord.setCreateTime(LocalDateTime.now());
        goodsRecord.setTableNumber(tj);
        goodsRecord.setRemark(remark);
        if (inventoryList.size() > 0) {
            Inventory i = inventoryList.get(0);
            goodsRecord.setProductId(i.getProductId());
        }

        goodsRecordService.save(goodsRecord);

        for (Inventory inventory : inventoryList) {


            LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Inventory::getSerialNumber, inventory.getSerialNumber());

            Inventory one = inventoryService.getOne(wrapper);

            // 如果仓库存在则不允许添加
            if (one != null) {
                isSaveInventory.add(one.getSerialNumber());
                continue;
            }

            // 添加到库存
            inventory.setId(UUID.randomUUID().toString());


            // 设置状态为启用
            inventory.setStatus(false);

            inventory.setCreateTime(LocalDateTime.now());
            inventory.setUpdateTime(LocalDateTime.now());

            inventoryService.save(inventory);

            // 添加记录
            AddGoods goods = new AddGoods();
            goods.setId(UUID.randomUUID().toString());
            goods.setTableNumber(tj);
            goods.setInventoryId(inventory.getId());
            goods.setProductId(inventory.getProductId());
            goods.setWarehouseId(inventory.getWarehouseId());
            goods.setCreateTime(LocalDateTime.now());
            addGoodsService.save(goods);
        }
        if (isSaveInventory.size() > 0) {
            StringBuilder sb = new StringBuilder();
            for (String s : isSaveInventory) {
                sb.append(s).append(",");
            }
            sb.append("该序列号已存在");
            return Result.fail(20002, sb.toString());
        }
        return Result.success("添加成功");
    }

    @PutMapping
    public Result<?> updateWareHouse(@RequestBody Inventory inventory) {

        inventory.setUpdateTime(LocalDateTime.now());
        inventoryService.updateById(inventory);

        return Result.success("更新成功");
    }

    // 删除序列号
    @DeleteMapping("/{id}")
    public Result<?> deleteWareHouse(@PathVariable("id") String id, @RequestBody String qz_token) {
        // 查询当前用户的权限是否可以删除仓库
        Object obj = redisTemplate.opsForValue().get(qz_token);
        if (obj != null) {
            // 将数据转成json数据
            User loginUser = JSON.parseObject(JSON.toJSONString(obj), User.class);
            // 删除仓库
            String role = loginUser.getRole();
            if (role.equals("admin")) {
                // 权限足够可以删除
                inventoryService.removeById(id);
                return Result.success("删除成功");
            } else {
                return Result.fail(20002, "你没有权限执行此操作");
            }
        } else {
            return Result.fail(20002, "删除失败");
        }
    }


    /**
     * 获取序列号在库情况
     *
     * @param
     * @return
     */
    @PostMapping("/getInWarehouseSerialNumber")
    public Result<?> getInWarehouseSerialNumber(@RequestBody Map<String, Object> transferData) {
        String warehouseId = (String) transferData.get("warehouseId");
        List<String> serialNumbers = (List<String>) transferData.get("serialNumbers");
        // 获取类型，false是收货，true是订单
        Boolean type = (Boolean) transferData.get("type");

        if (serialNumbers == null || warehouseId == null || type == null)
            return Result.fail(Code.UPDATE_FAIL_CODE, "数据格式有误");

        Map<String, Object> data = new HashMap<>();

        List<Map<String, String>> inWarehouseSerialNumbers = new ArrayList<>();
        List<Map<String, String>> outWarehouseSerialNumbers = new ArrayList<>();


        for (String serialNumber : serialNumbers) {
//            订单
            if (type) {
                // 获取订单ID
                LambdaQueryWrapper<OrderSerialNumber> serialNumberLambdaQueryWrapper = new LambdaQueryWrapper<>();
                serialNumberLambdaQueryWrapper.eq(OrderSerialNumber::getSerialNumber, serialNumber);

                // 收货序列号，查询待入库的
                serialNumberLambdaQueryWrapper.eq(OrderSerialNumber::getStatus, Code.DAI_CHU_KU);

                // 订单ID
                OrderSerialNumber orderSerialNumber = serialNumberService.getOne(serialNumberLambdaQueryWrapper);

                // 如果没有则设置默认状态
                if (orderSerialNumber == null) {
                    orderSerialNumber = new OrderSerialNumber();
                }

                LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Inventory::getSerialNumber, serialNumber);
                Inventory one = inventoryService.getOne(wrapper);

                Map<String, String> outWarehouseSerialNumber = new HashMap<>();


                // 查询序列号ID和状态
                if (one != null) {

                    // 查询序列号状态 如果是异常的则不添加进来
                    if (one.getWarehouseId().equals(warehouseId)) {
                        if (!one.getStatus()) {
                            Map<String, String> inWarehouseSerialNumber = new HashMap<>();

                            // 仓库名称
                            Warehouse warehouse = warehouseService.getById(one.getWarehouseId());
                            inWarehouseSerialNumber.put("serialNumber", serialNumber);
                            inWarehouseSerialNumber.put("warehouseName", warehouse.getWarehouseName());

                            // 获取商品名称
                            Product product = productService.getById(one.getProductId());
                            inWarehouseSerialNumber.put("productName", product.getGoodsName());

                            // 订单ID
                            inWarehouseSerialNumber.put("orderId", orderSerialNumber.getOrderId());

                            inWarehouseSerialNumbers.add(inWarehouseSerialNumber);

                        }
                    } else {
                        outWarehouseSerialNumber.put("serialNumber", serialNumber);
                        // 查询仓库名称
                        Warehouse warehouse = warehouseService.getById(one.getWarehouseId());
                        outWarehouseSerialNumber.put("warehouseName", warehouse.getWarehouseName());

                        // 获取商品名称
                        Product product = productService.getById(one.getProductId());
                        outWarehouseSerialNumber.put("productName", product.getGoodsName());

                        // 订单ID
                        outWarehouseSerialNumber.put("orderId", orderSerialNumber.getOrderId());
                        // 查询序列号状态
                    }

                } else {
                    outWarehouseSerialNumber.put("serialNumber", serialNumber);
                    outWarehouseSerialNumber.put("warehouseName", "未知仓库");
                    outWarehouseSerialNumber.put("productName", "未知");

                    // 订单ID
                    outWarehouseSerialNumber.put("orderId", orderSerialNumber.getOrderId());
                    // 查询序列号状态
                }


                if (outWarehouseSerialNumber.get("serialNumber") != null) {
                    outWarehouseSerialNumbers.add(outWarehouseSerialNumber);
                }
            } else {
                // 收货
                // 获取收货订单
                LambdaQueryWrapper<GoodsSerialNumber> goodsSerialNumberLambdaQueryWrapper = new LambdaQueryWrapper<>();
                goodsSerialNumberLambdaQueryWrapper.eq(GoodsSerialNumber::getSerialNumber, serialNumber);

                // 收货序列号，查询待入库的
                goodsSerialNumberLambdaQueryWrapper.eq(GoodsSerialNumber::getStatus, Code.DAI_RU_KU);

                // 订单ID
                GoodsSerialNumber goodsSerialNumber = goodsSerialNumberService.getOne(goodsSerialNumberLambdaQueryWrapper);

                // 如果没有则设置默认状态
                if (goodsSerialNumber == null) {
                    goodsSerialNumber = new GoodsSerialNumber();
                }

                // 获取商品
                LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Inventory::getSerialNumber, serialNumber);
                Inventory inventory = inventoryService.getOne(wrapper);

                Map<String, String> outWarehouseSerialNumber = new HashMap<>();


                // 查询序列号ID和状态
                if (inventory != null) {

                    // 查询序列号状态 如果是异常的则不添加进来
                    if (inventory.getWarehouseId().equals(warehouseId)) {
                        if (!inventory.getStatus()) {
                            Map<String, String> inWarehouseSerialNumber = new HashMap<>();

                            // 仓库名称
                            Warehouse warehouse = warehouseService.getById(inventory.getWarehouseId());
                            inWarehouseSerialNumber.put("serialNumber", serialNumber);
                            inWarehouseSerialNumber.put("warehouseName", warehouse.getWarehouseName());

                            // 获取商品名称
                            Product product = productService.getById(inventory.getProductId());
                            inWarehouseSerialNumber.put("productName", product.getGoodsName());

                            // 收货订单
                            inWarehouseSerialNumber.put("receiveGoodsId", goodsSerialNumber.getReceiveGoodsId());

                            inWarehouseSerialNumbers.add(inWarehouseSerialNumber);

                        }
                    } else {
                        outWarehouseSerialNumber.put("serialNumber", serialNumber);
                        // 查询仓库名称
                        Warehouse warehouse = warehouseService.getById(inventory.getWarehouseId());
                        outWarehouseSerialNumber.put("warehouseName", warehouse.getWarehouseName());

                        // 获取商品名称
                        Product product = productService.getById(inventory.getProductId());
                        outWarehouseSerialNumber.put("productName", product.getGoodsName());

                        // 订单ID
                        outWarehouseSerialNumber.put("receiveGoodsId", goodsSerialNumber.getReceiveGoodsId());
                        // 查询序列号状态
                    }

                } else {
                    outWarehouseSerialNumber.put("serialNumber", serialNumber);
                    outWarehouseSerialNumber.put("warehouseName", "未知仓库");
                    outWarehouseSerialNumber.put("productName", "未知");

                    // 订单ID
                    outWarehouseSerialNumber.put("receiveGoodsId", goodsSerialNumber.getReceiveGoodsId());
                    // 查询序列号状态
                }


                if (outWarehouseSerialNumber.get("serialNumber") != null) {
                    outWarehouseSerialNumbers.add(outWarehouseSerialNumber);
                }
            }


        }


        data.put("inWarehouseSerialNumber", inWarehouseSerialNumbers);
        data.put("outWarehouseSerialNumber", outWarehouseSerialNumbers);

        return Result.success(data);
    }


    /**
     * 导出设备档期表
     */
    @GetMapping("/getAllProductDangQi")
    public void getAllProductDangQi(HttpServletResponse response, @RequestParam String warehouseId) throws IOException {
        // 导出库充数量和预计寄回设备数量,通过Map格式写入Excel表格中
        /**
         * 格式是
         * 每一个设备是一个Map集合：{
         *          设备名称：
         *          当天在库设备：设备数量
         *          预计寄回日期：设备数量
         *          。。。。
         *  }
         */

        ExcelWriter writer = ExcelUtil.getWriter(true);


        // 获取所有寄回设备(先查询所有已寄回订单)
        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
        orderLambdaQueryWrapper.eq(Order::getOrderStatus, Code.YI_JI_HUI);
        orderLambdaQueryWrapper.isNotNull(Order::getGetReceiptDate); // 查询预计寄回时间不为空的值
        List<Order> orders = orderService.list(orderLambdaQueryWrapper);
        // 查询订单绑定的序列号
        List<OrderDto> orderDtoList = orderSerialNumberService.getOrderDtoList(orders); // 所有寄回订单和订单绑定的序列号（寄回订单获取预计寄回时间，设备序列号计算库存）

        // 所有预计寄回日期
        Set<LocalDate> allDate = new TreeSet<>(); // TreeSet自动排序
        for (OrderDto orderDto : orderDtoList) {
            // 统计所有寄回日期，今天之前的判断为今天
            if (orderDto.getGetReceiptDate().toLocalDate().isBefore(LocalDate.now())) {
                // 设置为惊天
                allDate.add(LocalDate.now());
            }
            allDate.add(orderDto.getGetReceiptDate().toLocalDate());
        }


        // 计算同一天寄回各个设备型号数量
        // 获取所有商品
        List<Product> products = productService.list();

        // 所有商品对应的Dto
        List<Map<String, Object>> data = new ArrayList<>();
        for (Product product : products) {
            Map<String, Object> productAndNumber = new HashMap<>();

            // 获取商品设备，在指定仓库中的
            LambdaQueryWrapper<Inventory> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Inventory::getWarehouseId, warehouseId);
            wrapper.eq(Inventory::getProductId, product.getId());

            List<Inventory> inventories = inventoryService.list(wrapper); // 商品对应在库的序列号
            productAndNumber.put(ExportCode.SHE_BEI_MING_CHENG, product.getGoodsName());
            productAndNumber.put(ExportCode.KU_CUN_SHU_LANG, inventories.size() + "");

            // 添加设备预计寄回日期
            for (LocalDate date : allDate) {
                productAndNumber.put(date.toString(), 0);
            }

            // 计算预计寄回设备数量
            /**
             * 计算方法，获取到序列号，查询商品名称，让当前日期的该设备数量+1
             */
            for (OrderDto orderDto : orderDtoList) {
                List<OrderSerialNumber> serialNumbers = orderDto.getSerialNumbers();
                for (OrderSerialNumber serialNumber : serialNumbers) {
                    try {
                        // 更具序列号查询商品名称
                        LambdaQueryWrapper<Inventory> inventoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
                        inventoryLambdaQueryWrapper.eq(Inventory::getSerialNumber, serialNumber.getSerialNumber());
                        Inventory inventory = inventoryService.getOne(inventoryLambdaQueryWrapper);

                        if (inventory != null) {
                            // 查询商品名称(更具商品ID判断商品是否相同，相同则在相应日期的档期加1)
                            if (product.getId().equals(inventory.getProductId())) {
                                // 设备相同
                                // 获取寄回日期
                                LocalDate getReceiptDate = orderDto.getGetReceiptDate().toLocalDate();
                                // 在档期+1
                                Integer num = (Integer) productAndNumber.get(getReceiptDate.toString());
                                num += 1;
                                productAndNumber.put(getReceiptDate.toString(), num);
                            }
                        }
                    } catch (Exception e) {
                        log.error(e.getMessage());
                    }

                }
            }


            // 获取序列号商品名称，设备名称
            data.add(productAndNumber);
        }


        List<Map<String, Object>> returnData = new ArrayList<>();
        for (Map<String, Object> datum : data) {
            for (LocalDate date : allDate) {
                if((Integer)datum.get(date.toString()) == 0){
                    datum.put(date.toString(), "");
                }
            }

            returnData.add(datum);
        }

        // 导出Excel
        writer.write(returnData);


        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("设备档期" + (LocalDate.now().toString()), "utf-8") + ".xlsx");
        ServletOutputStream outputStream = response.getOutputStream();
        writer.flush(outputStream, true);
        outputStream.flush();
        writer.close();
        outputStream.close();

    }
}
